<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
    <!-- <script src="https://lib.baomitu.com/vue/2.6.14/vue.min.js"></script> -->
  </head>
  <body>
    <div id="testkey"></div>
    <script>
      /*
      const vvm = new Vue({
        el: "#testkey",
        data: {
          arr: ["香蕉", "苹果", "橘子"],
        },
        methods: {
          add() {
            this.arr.unshift("橙子");
          },
        },
        template: `<div>
          <ul>
            <li v-for="(item, index) in arr" :key="item">
          <input type="checkbox" :checked="!index"/>{{item}}
        </li>
      </ul>
      <ul>
        <li v-for="(item, index) in arr" :key="index">
          <input type="checkbox" :checked="!index" />{{item}}
        </li>
        </ul>
        <p><button @click="add">add</button></p>
        </div>`,
      });
      */
    </script>
    <div id="app">
      <span> {{name}} {{a.b}} </span>
    </div>
    <script src="../dist/vue.js"></script>
    <script>
      /*
        Vue 是 MVVM 框架，（基于 MVC升级，弱化 Controller），有没有完全遵循 mvvm，因为传统 mvvm 框架是不能手动操作数据的，在 vue 中可以手动通过 ref 去操作组件数据

        Vue2 的核心：响应式原理， 使用 defineProperty 来监听数据的变化

          双向绑定主要体现在 v-model 上

          vm.$options 获取到用户传递所有参数

          vue2 中 $开头的属性，是不会变成响应式的，用户如果传递了带有 $的属性会被忽略，处理掉， data:{"$a": 124} vm.$a是获取不到的返回undefined

          vue2 的数据源 props data methods computed watch

          vue2 数组修改数据后实在麻烦就直接覆盖原始数据，暴力


          vue2中的响应式原理就是为对象的每个属性 添加 set 和 get，会递归遍历，因此，用户在写代码的时候对data的数据的对象嵌套不要太过于深，
          vue2中数组的长度和索引没有监控，
          vue2中的数组没有采用 defineProperty ，采用了函数的劫持重写的数组的 7 个方法，用户在调用的时候或执行这个这个方法，用户添加数据时会再次被劫持，后再执行数据的原生方法，因此数组中的对象也是响应式的

          渲染 Watcher： 是默认是创建一个组件，就会生成一个渲染 Watcher，
          v-if 在数据切换后， 需要再重新收集依赖


          依赖收集的流程
          一开始就走 defineReactive 方法把每个属性劫持监听，此时会个每个属性配置对应的 Dep（Dep 的目的是为了收集渲染 Wathcer）
          开始渲染组件之前，把组件的每个 Watcher 先绑定到 Dep.target 上
          开始渲染逻辑就会调用 render 方法，此时发生取值操作，去触发 get 函数，此时 Dep.target 上有对应的渲染 Watcher，就让 dep 和 watcher 创建关系，此时属性中就对应了dep中欧给你的存放的数组 watchers用来存储哪个watcher用到了该属性，同样watcher也会存储这依赖的所有属性 deps
          每个属性有一个 dep，dep记住了对应的watcher


          diff 算法是平级比对
          比对时候，主要比对标签名和 key来判断是不是同一个元素，如果标签和key都一样就认为是同一个元素

          v-for如果有增加或删除，不要使用索引做 key：diff比对是根据key比较



          React 本身是一个 V 框架，只是将数据转换成试图，并没有绑定操作，更新数据也是手动调用 setState 去更新的
          react 的数据源主要在 props 和 state data
      */

      // watch $watch
      /*
      const vm = new Vue({
        el: "#app",
        data: {
          name: "Timly",
          age: 1,
        },
        watch: {
          age: {
            handler: (newVal, oldVal) => {
              console.log("watch-4", newVal, oldVal);
            },
            immediate: true,
          },
          // name(newVal, oldVal) {
          //   console.log("watch-4", newVal, oldVal);
          // },
          name: [
            (newVal, oldVal) => {
              console.log("watch-1", newVal, oldVal);
            },
            {
              handler: (newVal, oldVal) => {
                console.log("watch-2", newVal, oldVal);
              },
              immediate: true,
            },
            "setName",
          ],
        },
        methods: {
          setName(newVal, oldVal) {
            console.log("watch-3", newVal, oldVal);
          },
        },
      });
      vm.$watch("name", (newVal, oldVal) => {
        console.log("watch-4", newVal, oldVal);
      });
      const t = setTimeout(() => {
        vm.name = "Tom";
        vm.age = 100;
      }, 3000);
      */

      const vm = new Vue({
        el: "#app",
        data: {
          name: "Timly",
          age: 1,
          a: {
            b: 99,
          },
        },
        watch: {
          "a.b": {
            handler: (newVal, oldVal) => {
              console.log("a.b", newVal, oldVal, 142);
            },
            immediate: true,
          },
        },
      });

      vm.$watch(
        "a.b",
        (newVal, oldVal) => {
          console.log("a.b", newVal, oldVal, 149);
        },
        { immediate: false }
      );

      const t = setTimeout(() => {
        vm.a.b = 999;
        console.log("setTimeout");
        clearTimeout(t);
      }, 3000);
    </script>
  </body>
</html>
